import mongoose, { Schema, Document } from 'mongoose';
import { DataSourceType, DataSourceStatus } from '@/types/datasource.types';

export interface IDataSource extends Document {
  name: string;
  type: DataSourceType;
  description?: string;
  status: DataSourceStatus;
  enabled: boolean;
  priority: number;

  connection: {
    url: string;
    apiKey?: string;
    username?: string;
    password?: string;
    headers?: Record<string, string>;
    timeout?: number;
    retryAttempts?: number;
    retryDelay?: number;
  };

  mapping: {
    alertNameField: string;
    severityField: string;
    statusField: string;
    timestampField: string;
    descriptionField: string;
    labelsField?: string;
    annotationsField?: string;
    customFields?: Record<string, string>;
  };

  valueMapping: {
    severity?: Record<string, 'critical' | 'high' | 'medium' | 'low'>;
    status?: Record<string, 'firing' | 'resolved' | 'acknowledged'>;
  };

  filters?: {
    includeRules?: Array<{
      field: string;
      operator: string;
      value: string | number | boolean;
    }>;
    excludeRules?: Array<{
      field: string;
      operator: string;
      value: string | number | boolean;
    }>;
  };

  transform?: {
    enabled: boolean;
    script?: string;
  };

  healthCheck?: {
    enabled: boolean;
    interval: number;
    endpoint?: string;
  };

  metadata: {
    createdBy: string;
    lastSyncAt?: Date;
    lastHealthCheck?: Date;
    totalAlertsReceived: number;
    errorCount: number;
  };

  createdAt: Date;
  updatedAt: Date;
}

const DataSourceSchema = new Schema<IDataSource>(
  {
    name: {
      type: String,
      required: true,
      trim: true,
      unique: true,
      maxlength: 100,
    },
    type: {
      type: String,
      required: true,
      enum: Object.values(DataSourceType),
    },
    description: {
      type: String,
      trim: true,
      maxlength: 500,
    },
    status: {
      type: String,
      enum: Object.values(DataSourceStatus),
      default: DataSourceStatus.INACTIVE,
    },
    enabled: {
      type: Boolean,
      default: true,
    },
    priority: {
      type: Number,
      default: 100,
      min: 0,
      max: 1000,
    },

    connection: {
      url: {
        type: String,
        required: true,
      },
      apiKey: String,
      username: String,
      password: String,
      headers: Schema.Types.Mixed,
      timeout: {
        type: Number,
        default: 30000,
        min: 1000,
        max: 300000,
      },
      retryAttempts: {
        type: Number,
        default: 3,
        min: 0,
        max: 10,
      },
      retryDelay: {
        type: Number,
        default: 1000,
        min: 100,
        max: 60000,
      },
    },

    mapping: {
      alertNameField: {
        type: String,
        default: 'alertname',
      },
      severityField: {
        type: String,
        default: 'severity',
      },
      statusField: {
        type: String,
        default: 'status',
      },
      timestampField: {
        type: String,
        default: 'timestamp',
      },
      descriptionField: {
        type: String,
        default: 'description',
      },
      labelsField: String,
      annotationsField: String,
      customFields: Schema.Types.Mixed,
    },

    valueMapping: {
      severity: Schema.Types.Mixed,
      status: Schema.Types.Mixed,
    },

    filters: {
      includeRules: [
        {
          field: String,
          operator: String,
          value: Schema.Types.Mixed,
        },
      ],
      excludeRules: [
        {
          field: String,
          operator: String,
          value: Schema.Types.Mixed,
        },
      ],
    },

    transform: {
      enabled: {
        type: Boolean,
        default: false,
      },
      script: String,
    },

    healthCheck: {
      enabled: {
        type: Boolean,
        default: true,
      },
      interval: {
        type: Number,
        default: 300, // 5 minutes
        min: 60,
        max: 3600,
      },
      endpoint: String,
    },

    metadata: {
      createdBy: {
        type: String,
        required: true,
      },
      lastSyncAt: Date,
      lastHealthCheck: Date,
      totalAlertsReceived: {
        type: Number,
        default: 0,
      },
      errorCount: {
        type: Number,
        default: 0,
      },
    },
  },
  {
    timestamps: true,
    toJSON: {
      virtuals: true,
      transform: (doc, ret) => {
        // 不返回敏感信息
        if (ret.connection?.password) {
          ret.connection.password = '***';
        }
        if (ret.connection?.apiKey) {
          ret.connection.apiKey = ret.connection.apiKey.substring(0, 8) + '***';
        }
        return ret;
      },
    },
  }
);

// 索引
DataSourceSchema.index({ name: 1 });
DataSourceSchema.index({ type: 1 });
DataSourceSchema.index({ enabled: 1, priority: 1 });
DataSourceSchema.index({ status: 1 });

// 虚拟字段 - 健康状态
DataSourceSchema.virtual('isHealthy').get(function (this: IDataSource) {
  return this.status === DataSourceStatus.ACTIVE;
});

// 虚拟字段 - 成功率
DataSourceSchema.virtual('successRate').get(function (this: IDataSource) {
  const total = this.metadata.totalAlertsReceived + this.metadata.errorCount;
  return total > 0 ? (this.metadata.totalAlertsReceived / total) * 100 : 0;
});

// 实例方法 - 测试连接
DataSourceSchema.methods.testConnection = async function () {
  // 这里会调用 dataSourceService 的 testDataSource 方法
  // 在 controller 层实现
  return { success: false, message: 'Not implemented in model' };
};

// 静态方法 - 获取启用的数据源
DataSourceSchema.statics.getEnabled = function () {
  return this.find({ enabled: true }).sort({ priority: 1 });
};

// 静态方法 - 按类型获取数据源
DataSourceSchema.statics.getByType = function (type: DataSourceType) {
  return this.find({ type });
};

// 前置钩子 - 保存前验证
DataSourceSchema.pre('save', async function (next) {
  if (this.isModified('password') && this.connection.password) {
    // 这里可以加密密码
    // this.connection.password = await encrypt(this.connection.password);
  }
  next();
});

// 后置钩子 - 删除后清理
DataSourceSchema.post('deleteOne', function (doc) {
  // 清理相关数据
  console.log(`Data source removed`);
});

const DataSource = mongoose.model<IDataSource>('DataSource', DataSourceSchema);

export default DataSource;
